﻿using System.Collections.Generic;
using System.Windows.Forms;
using DigitalRune.Windows.TextEditor;
using DigitalRune.Windows.TextEditor.Completion;
using Zove.Desktop.Properties;
using Zove.DesignTime;
using System.Text;
using Zove.Runtime;
using Zove.Runtime.Core;


namespace Zove.Desktop {
    public class ElementNode {
        public string Name {
            get;
            set;
        }

        public List<ElementNode> Children {
            get;
            set;
        }

        public ElementNode() {
            this.Children = new List<ElementNode>();
        }
    }

    public class CodeCompletionDataProvider : AbstractCompletionDataProvider {
        private readonly ImageList _imageList;

        public Dictionary<string, string> Instances {
            get;
            set;
        }

        public static Dictionary<string, Zove.DesignTime.ZoomClass> ClassCache {
            get;
            set;
        }

        public override ImageList ImageList {
            get { return _imageList; }
        }

        public CodeCompletionDataProvider() {
            // Create the image-list that is needed by the completion windows
            _imageList = new ImageList();
            //_imageList.Images.Add(Resources.TemplateIcon);
            //_imageList.Images.Add(Resources.FieldIcon);
            //_imageList.Images.Add(Resources.MethodIcon);

            this.Instances = new Dictionary<string, string>();
        }

        public CodeCompletionDataProvider(string k)
            : this() {
            this.w = k;
        }

        private string w = string.Empty;

        public ElementNode Root {
            get {
                ElementNode root = new ElementNode();

                ElementNode hello = new ElementNode();
                hello.Name = "hello";
                root.Children.Add(hello);

                ElementNode world = new ElementNode();
                world.Name = "world";
                hello.Children.Add(world);

                ElementNode me = new ElementNode();
                me.Name = "you";
                world.Children.Add(me);

                return root;
            }
        }

        public override ICompletionData[] GenerateCompletionData(
            string fileName, TextArea textArea, char charTyped) {
            //string content = GetTempClass(
            //    textArea.Document.TextContent, textArea.Caret.Offset);
            //ZvClass context = GetCurrentClass(content);

            //string text = FindIdentifier(
            //    textArea.Document.TextContent, textArea.Caret.Offset);
            //ZvClass c = GetClassByInstance(text, context);

            //List<ICompletionData> completionData = new List<ICompletionData>();
            //foreach (ZvVariable v in c.Variables)
            //{
            //    DefaultCompletionData dcd
            //        = new DefaultCompletionData(v.Name, v.Type, 1);
            //    completionData.Add(dcd);
            //}

            //return completionData.ToArray();


            List<DefaultCompletionData> data = new List<DefaultCompletionData>();
            data.Add(
                new DefaultCompletionData("from", "", 1));
            data.Add(new DefaultCompletionData("select", "", 1));
            data.Add(new DefaultCompletionData("where", "", 1));

            if (!string.IsNullOrEmpty(w)) {
                string[] wd = w.Split('.');
                ElementNode n = Root;
                foreach (string x in wd) {
                    n = GetNodeById(x, n);
                }

                if (n != null) {
                    foreach (ElementNode c in n.Children) {
                        data.Add(new DefaultCompletionData(c.Name, "", 1));
                    }
                }
            }

            return data.ToArray();
        }

        public ElementNode GetNodeById(string x, ElementNode root) {
            foreach (ElementNode child in root.Children) {
                if (child.Name == x) {
                    return child;
                }
            }

            return null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="p"></param>
        /// <param name="p_2"></param>
        /// <returns></returns>
        public static string GetTempClass(string p, int p_2) {
            string content = p.Substring(0, p_2);
            int lastComma = content.LastIndexOf(';');
            content = content.Substring(0, lastComma + 1) + "}";

            return content;
        }

        /// <summary>
        /// content file
        /// </summary>
        /// <param name="content"></param>
        /// <returns></returns>
        public static ZoomClass GetCurrentClass(string content) {
            ZoomClass c = new ZoomClass();

            DefaultClassLoader loader = new DefaultClassLoader();
            c = ZoveDependencyManager.Instance.ClassLoader.LoadFromSource(content);

            return c;
        }

        public static ZoomClass GetClassByInstance(string text, ZoomClass current) {
            ZoomClass c = null;
            string[] instances = text.Split('.');

            c = current;
            for (int index = 0; index < instances.Length; index++) {
                foreach (ZoomVariable v in c.Variables) {
                    if (v.Type != "factor" && v.Name == instances[index]) {
                        c = GetClassByName(v.Type);
                    }
                }
            }

            return c;
        }

        public static Zove.DesignTime.ZoomClass GetClassByName(string className) {
            if (ClassCache == null) {
                ClassCache = new Dictionary<string, Zove.DesignTime.ZoomClass>();
            }

            if (ClassCache.ContainsKey(className)) {
                return ClassCache[className];
            }

            Zove.DesignTime.ZoomClass c
                = ZoveDependencyManager.Instance.ClassLoader.LoadByClassName(className);

            ClassCache[className] = c;

            return c;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="p"></param>
        /// <param name="p_2"></param>
        /// <returns></returns>
        public static string FindIdentifier(string p, int p_2) {
            StringBuilder buff = new StringBuilder();

            for (int index = p_2 - 1; index >= 0
                && (char.IsLetterOrDigit(p[index]) || p[index] == '.');
                --index) {
                buff.Insert(0, p[index]);
            }

            return buff.ToString();
        }
    }
}
